package com.example.demo.controller;

import com.alibaba.fastjson.JSONObject;
import com.example.demo.common.Constant;
import com.example.demo.model.entity.ActivityModel;
import com.example.demo.model.entity.AdModel;
import com.example.demo.model.entity.ApplyModel;
import com.example.demo.model.entity.UserModel;
import com.example.demo.service.impl.ActivityService;
import com.example.demo.service.impl.AdService;
import com.example.demo.service.impl.UserService;
import org.apache.commons.lang3.StringUtils;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Sort;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;
import sun.misc.BASE64Decoder;

import javax.annotation.Resource;
import javax.persistence.criteria.*;
import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;

@Controller
@RequestMapping(value = Constant.API_VERSION + "/activity")
public class ActivityController {

    @Resource
    ActivityService activityService;

    @Resource
    UserService userService;

    @RequestMapping(value = "", method = RequestMethod.POST)
    @ResponseBody
    public ActivityModel save(@RequestBody ActivityModel model) throws Exception {
        if (model.getStartTime() == null) {
            throw new RuntimeException(MessageFormat.format(Constant.ERROR_FORMAT, 400, "活动开始时间必填"));
        }
        if (model.getEndTime() == null) {
            throw new RuntimeException(MessageFormat.format(Constant.ERROR_FORMAT, 400, "活动结束时间必填"));
        }
        if (model.getApplyStartTime() == null) {
            throw new RuntimeException(MessageFormat.format(Constant.ERROR_FORMAT, 400, "报名开始时间必填"));
        }
        if (model.getApplyEndTime() == null) {
            throw new RuntimeException(MessageFormat.format(Constant.ERROR_FORMAT, 400, "报名结束时间必填"));
        }
        if (StringUtils.isEmpty(model.getActivityName())) {
            throw new RuntimeException(MessageFormat.format(Constant.ERROR_FORMAT, 400, "活动名称必填"));
        }
        if (model.getStartTime() >= model.getEndTime()) {
            throw new RuntimeException(MessageFormat.format(Constant.ERROR_FORMAT, 400, "活动开始时间必须小于结束时间"));
        }
        if (model.getApplyStartTime() >= model.getApplyEndTime()) {
            throw new RuntimeException(MessageFormat.format(Constant.ERROR_FORMAT, 400, "报名开始时间必须小于结束时间"));
        }
        if (StringUtils.isEmpty(model.getAddress())) {
            throw new RuntimeException(MessageFormat.format(Constant.ERROR_FORMAT, 400, "活动地址必填"));
        }
        model.setActivityId(UUID.randomUUID().toString());
        model.setCreateTime(System.currentTimeMillis());
        return activityService.save(model);
    }

    @RequestMapping(value = "/{activity_id}", method = RequestMethod.GET)
    @ResponseBody
    public ActivityModel getActivity(@RequestHeader("Authorization") String token, @PathVariable(value = "activity_id") String activityId) throws Exception {
        ActivityModel activity = activityService.getById(activityId);
        BASE64Decoder decoder = new BASE64Decoder();
        String currentUid = new String(decoder.decodeBuffer(token), "UTF-8");
        if (activity == null) {
            throw new RuntimeException(MessageFormat.format(Constant.ERROR_FORMAT, 400, "活动不存在"));
        }
        activity.setHasApply(activityService.hasApply(currentUid, activityId));
        return activity;
    }

    @RequestMapping(value = "/{activity_id}", method = RequestMethod.PUT)
    @ResponseBody
    public ActivityModel update(@PathVariable(value = "activity_id") String activityId, @RequestBody ActivityModel model) throws Exception {
        ActivityModel activity = activityService.getById(activityId);
        if (activity == null) {
            throw new RuntimeException(MessageFormat.format(Constant.ERROR_FORMAT, 400, "活动不存在"));
        }
        if (StringUtils.isNotEmpty(model.getActivityContent())) {
            activity.setActivityContent(model.getActivityContent());
        }
        if (StringUtils.isNotEmpty(model.getActivityDesc())) {
            activity.setActivityDesc(model.getActivityDesc());
        }
        if (StringUtils.isNotEmpty(model.getActivityName())) {
            activity.setActivityName(model.getActivityName());
        }
        if (model.getActivityStatus() != null) {
            activity.setActivityStatus(model.getActivityStatus());
        }
        if (model.getEndTime() != null) {
            activity.setEndTime(model.getEndTime());
        }
        if (model.getApplyStartTime() != null) {
            activity.setApplyStartTime(model.getApplyStartTime());
        }
        if (model.getApplyEndTime() != null) {
            activity.setApplyEndTime(model.getApplyEndTime());
        }
        if (model.getStartTime() != null) {
            activity.setStartTime(model.getStartTime());
        }
        if (model.getActivityImg() != null) {
            activity.setEndTime(model.getEndTime());
        }
        if (model.getLimitPeople() != null) {
            activity.setLimitPeople(model.getLimitPeople());
        }
        if (model.getActivityIndex() != null) {
            activity.setActivityIndex(model.getActivityIndex());
        }
        if (StringUtils.isNotEmpty(model.getAddress())) {
            activity.setAddress(model.getAddress());
        }
        if (StringUtils.isNotEmpty(model.getActivityImg())) {
            activity.setActivityImg(model.getActivityImg());
        }
        if (StringUtils.isNotEmpty(model.getProviderUrl())) {
            activity.setProviderUrl(model.getProviderUrl());
        }
        return activityService.save(activity);
    }


    @RequestMapping(value = "/action/apply", method = RequestMethod.POST)
    @ResponseBody
    public void apply(@RequestHeader("Authorization") String token, @RequestBody ApplyModel model) throws Exception {
        BASE64Decoder decoder = new BASE64Decoder();
        String currentUid = new String(decoder.decodeBuffer(token), "UTF-8");
        ActivityModel activity = activityService.getById(model.getActivityId());
        if (activity == null) {
            throw new RuntimeException(MessageFormat.format(Constant.ERROR_FORMAT, 400, "活动不存在"));
        }
//        if (activity.getStartTime() < System.currentTimeMillis() && activity.getEndTime() > System.currentTimeMillis()) {
//            throw new RuntimeException(MessageFormat.format(Constant.ERROR_FORMAT, 400, "非活动报名开始到结束时间内不允许报名"));
//        }
        if (!(activity.getApplyStartTime() < System.currentTimeMillis() && activity.getApplyEndTime() > System.currentTimeMillis())) {
            throw new RuntimeException(MessageFormat.format(Constant.ERROR_FORMAT, 400, "非活动报名开始到结束时间内不允许报名"));
        }
        UserModel user = userService.getByUid(currentUid);
        activityService.apply(model.getActivityId(), user.getUserId());
    }


    @RequestMapping(value = "/action/sign", method = RequestMethod.POST)
    @ResponseBody
    public void sign(@RequestHeader("Authorization") String token, @RequestBody ApplyModel model) throws Exception {
        BASE64Decoder decoder = new BASE64Decoder();
        String currentUid = new String(decoder.decodeBuffer(token), "UTF-8");
        UserModel user = userService.getByUid(currentUid);
        activityService.sign(model.getActivityId(), user.getUserId());
    }


    @RequestMapping(value = "/{activity_id}", method = RequestMethod.DELETE)
    @ResponseBody
    public void delete(@PathVariable(value = "activity_id") String activityId) throws Exception {
        activityService.delete(activityId);
    }

    @RequestMapping(value = "", method = RequestMethod.GET)
    @ResponseBody
    public JSONObject getActivityPage(@RequestParam(value = "page_size", defaultValue = "10") String pageSize, @RequestParam(value = "page_number", defaultValue = "1") String pageNumber,
                                      @RequestParam(value = "shop_id", defaultValue = "") final String shopId, @RequestParam(value = "activity_status", defaultValue = "") final String activityStatus,
                                      @RequestParam(value = "keyword", defaultValue = "") final String keyword,
                                      @RequestParam(value = "user_id", defaultValue = "") final String userId) throws Exception {
        Page<ActivityModel> adPage = activityService.getActivityPage(new Specification() {
            @Override
            public Predicate toPredicate(Root root, CriteriaQuery criteriaQuery, CriteriaBuilder criteriaBuilder) {
                List<Predicate> predicateList = new ArrayList<>();
                if (StringUtils.isNotEmpty(shopId)) {
                    Path<Integer> shopIdPath = root.get("shopId");
                    predicateList.add(criteriaBuilder.equal(shopIdPath, shopId));
                }
                if (StringUtils.isNotEmpty(keyword)) {
                    Path<String> namePath = root.get("activityName");
                    predicateList.add(criteriaBuilder.like(namePath, "%" + keyword + "%"));
                }
                if (StringUtils.isNotEmpty(activityStatus)) {
                    Path<Integer> statusPath = root.get("activityStatus");
                    predicateList.add(criteriaBuilder.equal(statusPath, Integer.valueOf(activityStatus)));
                }

                if (StringUtils.isNotEmpty(userId)) {
                    Join<ActivityModel, ApplyModel> join = root.join(root.getModel().getSet("apply", ApplyModel.class), JoinType.INNER);
                    predicateList.add(criteriaBuilder.equal(join.get("userId"), userId));
                }
//                Path<Long> startPath = root.get("applyStartTime");
//                Path<Long> endPath = root.get("applyEndTime");
//                predicateList.add(criteriaBuilder.lt(startPath, System.currentTimeMillis()));
//                predicateList.add(criteriaBuilder.gt(endPath, System.currentTimeMillis()));
                criteriaQuery.where(predicateList.toArray(new Predicate[predicateList.size()]));
                return null;
            }
        }, new PageRequest(Integer.valueOf(pageNumber) - 1, Integer.valueOf(pageSize), new Sort(Sort.Direction.DESC, "createTime")));


        List<ActivityModel> activityModelList = adPage.getContent();
        for (ActivityModel a : activityModelList) {
            if (System.currentTimeMillis() > a.getApplyEndTime()) {
                a.setActivityStatus(1);
            }
        }

        JSONObject result = new JSONObject();
        result.put("total", adPage.getTotalElements());
        result.put("items", activityModelList);
        return result;
    }

}
